#include "../Base/stdafx.h"
#include "Bone.h"
#include "../Effects/Effect.h"
#include "../Effects/EffectLib.h"
#include "../Base/vertex.h"
#include "../Base/GameEngine.h"
#include "../Base/DXDevice.h"

Bone::Bone( const tstring& name, float length, int id )
{
	m_Length = length;

	MeshDesc mDesc;
	mDesc.id = id;
	mDesc.name = name;
	mDesc.ownRender = true;
	Init(mDesc);
	m_AnimStep = 0;

}

Bone::~Bone()
{
	if(m_VertexBuffer) m_VertexBuffer->Release();
	if(m_IndexBuffer) m_IndexBuffer->Release();
	if(m_Layout) m_Layout->Release();
}

void Bone::Init( const MeshDesc& mDesc )
{
	m_MeshDesc = mDesc;
	float width = (sqrt(m_Length) / 5.0f);

	vector<VertexPNC> v;
	v.push_back(VertexPNC(0, 0, 0, -1, 0, 0, D3DXVECTOR4(.8f, .8f, .8f, 1)));
	v.push_back(VertexPNC(m_Length, 0, 0, 1, 0, 0, D3DXVECTOR4(.8f, .8f, .8f, 1)));
	v.push_back(VertexPNC(m_Length/2, -width, -width, 0, -0.5f, -0.5f, D3DXVECTOR4(.8f, .8f, .8f, 1)));
	v.push_back(VertexPNC(m_Length/2, -width, width, 0, -0.5f, 0.5f, D3DXVECTOR4(.8f, .8f, .8f, 1)));
	v.push_back(VertexPNC(m_Length/2, width, width, 0, 0.5f, 0.5f, D3DXVECTOR4(.8f, .8f, .8f, 1)));
	v.push_back(VertexPNC(m_Length/2, width, -width, 0, 0.5f, -0.5f, D3DXVECTOR4(.8f, .8f, .8f, 1)));

	vector<DWORD> i;
	i.push_back(0);i.push_back(3);i.push_back(2);
	i.push_back(0);i.push_back(4);i.push_back(3);
	i.push_back(0);i.push_back(5);i.push_back(4);
	i.push_back(0);i.push_back(2);i.push_back(5);
	i.push_back(1);i.push_back(2);i.push_back(3);
	i.push_back(1);i.push_back(3);i.push_back(4);
	i.push_back(1);i.push_back(4);i.push_back(5);
	i.push_back(1);i.push_back(5);i.push_back(2);

	D3D10_BUFFER_DESC vDesc;
	vDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	vDesc.ByteWidth = sizeof(VertexPNC) * 6;
	vDesc.CPUAccessFlags = NULL;
	vDesc.MiscFlags = NULL;
	vDesc.Usage = D3D10_USAGE_DEFAULT;
	D3D10_SUBRESOURCE_DATA vData;
	vData.pSysMem = &v[0];
	HR(GETDEVICE->CreateBuffer( &vDesc, &vData, &m_VertexBuffer ));

	D3D10_BUFFER_DESC iDesc;
	iDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
	iDesc.ByteWidth = sizeof(DWORD) * 24;
	iDesc.CPUAccessFlags = NULL;
	iDesc.MiscFlags = NULL;
	iDesc.Usage = D3D10_USAGE_DEFAULT;
	D3D10_SUBRESOURCE_DATA iData;
	iData.pSysMem = &i[0];
	HR(GETDEVICE->CreateBuffer( &iDesc, &iData, &m_IndexBuffer ));

	m_Effect = EFFECTLIB->CreateEffect(_T("./Shaders/posnormcol.fx"));
	m_Tech = m_Effect->GetTechniqueByName("Render");
	m_WorldVar = m_Effect->GetVariableByName("g_World")->AsMatrix();
	m_WVPVar = m_Effect->GetVariableByName("g_WorldViewProj")->AsMatrix();
	m_PosLightVar = m_Effect->GetVariableByName("g_PosLight")->AsVector();

	DXDEVICE->GetMatrixen(m_World, m_View, m_Proj);

	this->GetTotalTranspose();

	const D3D10_INPUT_ELEMENT_DESC layoutScene[] =
	{
		{ "POSITION",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "NORMAL",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
	};
	UINT numElementsScene = sizeof(layoutScene)/sizeof(layoutScene[0]);
	D3D10_PASS_DESC passDesc;
	m_Tech->GetPassByIndex(0)->GetDesc(&passDesc);
	DXDEVICE->GetDevice()->CreateInputLayout(layoutScene, numElementsScene, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize,  &m_Layout);

}

void Bone::Draw()
{
	DXDEVICE->GetMatrixen(m_View, m_Proj);
	m_WorldVar->SetMatrix((float*) &m_World);
	m_WVPVar->SetMatrix((float*) &(m_World * m_View * m_Proj));
	m_PosLightVar->SetFloatVector((float*)&DXDEVICE->GetLight().dir);

	UINT stride = sizeof(VertexPNC);
	UINT offset = 0;
	GETDEVICE->IASetInputLayout(m_Layout);
	GETDEVICE->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	GETDEVICE->IASetVertexBuffers(0, 1, &m_VertexBuffer, &stride, &offset);
	GETDEVICE->IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R32_UINT, 0);


	D3D10_TECHNIQUE_DESC tech;
	m_Tech->GetDesc( &tech);
	for(UINT t = 0; t < tech.Passes; ++t)
	{
		m_Tech->GetPassByIndex(t)->Apply(0);
		DXDEVICE->GetDevice()->DrawIndexed(24, 0, 0);
	}

}

const tstring& Bone::GetName() const
{
	return m_MeshDesc.name;
}

int Bone::GetId() const
{
	return m_MeshDesc.id;
}

void Bone::SetAnimation( const vector<D3DXVECTOR3>& rotations )
{
	m_Animatie = rotations;
}

void Bone::NextStep()
{
	if(m_Animatie.size() != 0)
	{
		++m_AnimStep;
		if(m_AnimStep == m_Animatie.size()) m_AnimStep = 0;
		this->SetRotation(m_Animatie.at(m_AnimStep));
	}
}